<?php

namespace app\model\oa;

use app\model\BaseModel;
use think\model\concern\SoftDelete;

/**
 * 请假申请模型
 * 
 * @property int $id 主键ID
 * @property int $admin_id 申请人ID
 * @property int $leave_type 请假类型：1事假 2病假 3年假 4婚假 5产假 6丧假 7调休 8其他
 * @property string $start_time 开始时间
 * @property string $end_time 结束时间
 * @property float $duration 请假时长(天)
 * @property string $reason 请假原因
 * @property string $attachment 附件
 * @property int $status 审批状态：1待审批 2已通过 3已拒绝 4已撤销
 * @property int $approve_admin_id 审批人ID
 * @property string $approve_time 审批时间
 * @property string $approve_remark 审批备注
 * @property int $create_time 创建时间
 * @property int $update_time 更新时间
 * @property int $delete_time 删除时间
 */
class Leaves extends BaseModel
{
    use SoftDelete;

    protected $name = 'oa_leaves';
    protected $pk = 'id';

    // 请假类型常量
    const TYPE_PERSONAL = 1;    // 事假
    const TYPE_SICK = 2;        // 病假
    const TYPE_ANNUAL = 3;      // 年假
    const TYPE_MARRIAGE = 4;    // 婚假
    const TYPE_MATERNITY = 5;   // 产假
    const TYPE_FUNERAL = 6;     // 丧假
    const TYPE_COMPENSATORY = 7; // 调休
    const TYPE_OTHER = 8;       // 其他

    // 审批状态常量
    const STATUS_PENDING = 1;   // 待审批
    const STATUS_APPROVED = 2;  // 已通过
    const STATUS_REJECTED = 3;  // 已拒绝
    const STATUS_CANCELLED = 4; // 已撤销

    // 字段类型转换
    protected $type = [
        'id' => 'integer',
        'admin_id' => 'integer',
        'leave_type' => 'integer',
        'duration' => 'float',
        'status' => 'integer',
        'approve_admin_id' => 'integer',
        'create_time' => 'timestamp',
        'update_time' => 'timestamp',
        'delete_time' => 'timestamp',
    ];

    /**
     * 关联申请人
     */
    public function admin()
    {
        return $this->belongsTo('app\model\admin\User', 'admin_id', 'id');
    }

    /**
     * 关联审批人
     */
    public function approveAdmin()
    {
        return $this->belongsTo('app\model\admin\User', 'approve_admin_id', 'id');
    }

    /**
     * 获取请假列表
     */
    public static function getList($params = [])
    {
        $query = self::with(['admin', 'approveAdmin']);

        // 按申请人筛选
        if (!empty($params['admin_id'])) {
            $query->where('admin_id', $params['admin_id']);
        }

        // 按审批人筛选
        if (!empty($params['approve_admin_id'])) {
            $query->where('approve_admin_id', $params['approve_admin_id']);
        }

        // 按请假类型筛选
        if (!empty($params['leave_type'])) {
            $query->where('leave_type', $params['leave_type']);
        }

        // 按审批状态筛选
        if (!empty($params['status'])) {
            $query->where('status', $params['status']);
        }

        // 按时间范围筛选
        if (!empty($params['start_date'])) {
            $query->where('start_time', '>=', $params['start_date'] . ' 00:00:00');
        }
        if (!empty($params['end_date'])) {
            $query->where('end_time', '<=', $params['end_date'] . ' 23:59:59');
        }

        // 按关键词搜索
        if (!empty($params['keyword'])) {
            $query->where(function($q) use ($params) {
                $q->where('reason', 'like', '%' . $params['keyword'] . '%');
            });
        }

        return $query->order('id desc')->paginate($params['limit'] ?? 15);
    }

    /**
     * 获取我的请假申请
     */
    public static function getMyLeaves($admin_id, $params = [])
    {
        $params['admin_id'] = $admin_id;
        return self::getList($params);
    }

    /**
     * 获取待我审批的请假申请
     */
    public static function getPendingApprovals($approve_admin_id, $params = [])
    {
        $params['approve_admin_id'] = $approve_admin_id;
        $params['status'] = self::STATUS_PENDING;
        return self::getList($params);
    }

    /**
     * 提交请假申请
     */
    public static function submitLeave($data = [])
    {
        $leave = new self();
        $leave->admin_id = $data['admin_id'];
        $leave->leave_type = $data['leave_type'];
        $leave->start_time = $data['start_time'];
        $leave->end_time = $data['end_time'];
        $leave->duration = self::calculateDuration($data['start_time'], $data['end_time']);
        $leave->reason = $data['reason'] ?? '';
        $leave->attachment = $data['attachment'] ?? '';
        $leave->status = self::STATUS_PENDING;
        $leave->approve_admin_id = $data['approve_admin_id'] ?? 0;

        return $leave->save();
    }

    /**
     * 计算请假时长（天）
     */
    public static function calculateDuration($start_time, $end_time)
    {
        $start = strtotime($start_time);
        $end = strtotime($end_time);
        
        if ($end <= $start) {
            return 0;
        }

        // 计算天数，精确到小数点后1位
        $duration = ($end - $start) / (24 * 3600);
        return round($duration, 1);
    }

    /**
     * 审批请假申请
     */
    public static function approveLeave($id, $approve_admin_id, $status, $remark = '')
    {
        $leave = self::find($id);
        if (!$leave) {
            return false;
        }

        $leave->status = $status;
        $leave->approve_admin_id = $approve_admin_id;
        $leave->approve_time = date('Y-m-d H:i:s');
        $leave->approve_remark = $remark;

        return $leave->save();
    }

    /**
     * 撤销请假申请
     */
    public static function cancelLeave($id, $admin_id)
    {
        $leave = self::where('id', $id)->where('admin_id', $admin_id)->find();
        if (!$leave) {
            return false;
        }

        if ($leave->status != self::STATUS_PENDING) {
            throw new \Exception('只能撤销待审批的申请');
        }

        $leave->status = self::STATUS_CANCELLED;
        return $leave->save();
    }

    /**
     * 获取请假统计
     */
    public static function getStats($admin_id, $year = null)
    {
        if (!$year) {
            $year = date('Y');
        }

        $start_date = $year . '-01-01';
        $end_date = $year . '-12-31';

        $stats = self::where('admin_id', $admin_id)
            ->whereBetween('start_time', [$start_date . ' 00:00:00', $end_date . ' 23:59:59'])
            ->field([
                'COUNT(*) as total_count',
                'SUM(CASE WHEN status = 1 THEN 1 ELSE 0 END) as pending_count',
                'SUM(CASE WHEN status = 2 THEN 1 ELSE 0 END) as approved_count',
                'SUM(CASE WHEN status = 3 THEN 1 ELSE 0 END) as rejected_count',
                'SUM(CASE WHEN status = 4 THEN 1 ELSE 0 END) as cancelled_count',
                'SUM(CASE WHEN status = 2 THEN duration ELSE 0 END) as approved_days',
                'SUM(CASE WHEN leave_type = 3 AND status = 2 THEN duration ELSE 0 END) as annual_days_used',
            ])
            ->find();

        return $stats;
    }

    /**
     * 获取请假类型文本
     */
    public function getLeaveTypeTextAttr($value, $data)
    {
        $typeMap = [
            self::TYPE_PERSONAL => '事假',
            self::TYPE_SICK => '病假',
            self::TYPE_ANNUAL => '年假',
            self::TYPE_MARRIAGE => '婚假',
            self::TYPE_MATERNITY => '产假',
            self::TYPE_FUNERAL => '丧假',
            self::TYPE_COMPENSATORY => '调休',
            self::TYPE_OTHER => '其他',
        ];
        return $typeMap[$data['leave_type']] ?? '未知';
    }

    /**
     * 获取状态文本
     */
    public function getStatusTextAttr($value, $data)
    {
        $statusMap = [
            self::STATUS_PENDING => '待审批',
            self::STATUS_APPROVED => '已通过',
            self::STATUS_REJECTED => '已拒绝',
            self::STATUS_CANCELLED => '已撤销',
        ];
        return $statusMap[$data['status']] ?? '未知';
    }

    /**
     * 检查时间冲突
     */
    public static function checkTimeConflict($admin_id, $start_time, $end_time, $exclude_id = 0)
    {
        $query = self::where('admin_id', $admin_id)
            ->where('status', 'in', [self::STATUS_PENDING, self::STATUS_APPROVED])
            ->where(function($query) use ($start_time, $end_time) {
                $query->where(function($q) use ($start_time, $end_time) {
                    $q->where('start_time', '<=', $start_time)
                      ->where('end_time', '>=', $start_time);
                })->whereOr(function($q) use ($start_time, $end_time) {
                    $q->where('start_time', '<=', $end_time)
                      ->where('end_time', '>=', $end_time);
                })->whereOr(function($q) use ($start_time, $end_time) {
                    $q->where('start_time', '>=', $start_time)
                      ->where('end_time', '<=', $end_time);
                });
            });

        if ($exclude_id > 0) {
            $query->where('id', '<>', $exclude_id);
        }

        return $query->count() > 0;
    }

    /**
     * 搜索器：按请假类型
     */
    public function searchLeaveTypeAttr($query, $value)
    {
        $query->where('leave_type', $value);
    }

    /**
     * 搜索器：按审批状态
     */
    public function searchStatusAttr($query, $value)
    {
        $query->where('status', $value);
    }

    /**
     * 搜索器：按申请人ID
     */
    public function searchAdminIdAttr($query, $value)
    {
        $query->where('admin_id', $value);
    }

    /**
     * 搜索器：按审批人ID
     */
    public function searchApproveAdminIdAttr($query, $value)
    {
        $query->where('approve_admin_id', $value);
    }

    /**
     * 搜索器：按时间范围
     */
    public function searchTimeRangeAttr($query, $value)
    {
        if (is_array($value) && count($value) == 2) {
            $query->where('start_time', '>=', $value[0] . ' 00:00:00')
                  ->where('end_time', '<=', $value[1] . ' 23:59:59');
        }
    }
}